Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: useEventListener EventMap generic override + EventTarget & refactor: multiple overloads to single mapped type #657

Open
wants to merge 30 commits into
base: master
Choose a base branch
from

Conversation

JimGitFE
Copy link

@JimGitFE JimGitFE commented Nov 18, 2024

Changelog

This PR introduces several improvements aimed at reducing complexity and increasing flexibility in the codebase:

  1. 🔨 Refactor: Reduced Code Duplication:

  • Decreased the total number of lines by consolidating overloads into a single Map declaration.
  • This approach enhances maintainability and simplifies the addition of new entries.
  1. ✨ Feature: Enhanced Type Safety:

  • Added a generic type for overriding any other map declared within the hook.
  • Ensures that only the specified eventMap generic type is utilized, offering stricter type control and greater adaptability.
  • EventTarget Based Implemented add EventTarget support to useEventListener #585 +(useRef or straight DOM Element as config.element argument) + AudioNode...
  1. 🔨 Refactor: Parameter Simplification:

  • Merged two optional parameters into a single configuration object parameter config .
  • Instead of having many optional parameters. This is more readable and scalable.

In Depth Changes

  1. 🔨 Refactor: Improved Readability & future refactors (by decreasing code size)

Replaced Overloads with Generic map from Element (string) to [Element, EventMap] tuple + 2 Utility constructs

/** Element as string to Matching EventMap */
type ElementToEventMap = {
   Window: [Window, WindowEventMap]
   HTMLElement: [HTMLElement, HTMLElementEventMap]
   Document: [Document, DocumentEventMap]
   ...
  1. ✨ Feature: Enhanced Type Safety

Custom EventMap Generic (overrides all Event to Element Mapping declarations in hook)

useEventListener<{ "user-storage": User }>("user-storage", (updatedUser) => console.log(updatedUser.email))

Globally declared CustomEventMap always available (applied to all DOM Elements, except when custom generic is used)

// globals.d.ts
declare global {
   /** Extends EventMap declarations for all DOM Elements (intersection)*/
   interface CustomEventMap {
      'my-custom-event': CustomEvent<{ isCustom: boolean }>
   }
   /** Intersects EventMap declarations for DOM Window Element (default DOM target for hook listener) */
   interface WindowEventMap {
      'my-custom-event': CustomEvent<{ hash: string }>
   }
}
  1. 🔨 Refactor Parameter Simplification

Optional Arguments element?: RefObject<T> & options?: boolean | AddEventListenerOptions moved to single optional Object argument config

const ref = useRef<HTMLDivElement>(null)
const options = { capture: true, once: true }
// 3rd Parameter `config`
useEventListener("mousedown", (value) => console.log(value.pageX), { ref, options })

Adding a new ref Element to Event map

Previously an overload was needed (+6 lines). Now adding a key-value pair to the ElementToEventMap: which value is a tuple containing the element type and its corresponding event map type (+1 line)

Usage Preview

import { useEventListener } from "@/hooks"
import { useRef } from "react"

const App: React.FC = () => {
   const element = useRef<HTMLDivElement>(null)
   const notARefObjectInstance = window // Either ref of a DOM Element or an Element Works

   useEventListener("mousedown", (value) => console.log(value.pageX), { element })
   useEventListener("mousedown", (value) => console.log(value.pageX), { element: notARefObjectInstance  })

   // Custom EventMap Override
   useEventListener<{ "order": { name: string; orderId: number } }>("order", (event) => console.log(event.orderId))

   return (
      <div ref={element} style={{ width: "200px", height: "200px", backgroundColor: "lightblue" }}>
         Click me!
      </div>
   )
}

export default App
  • Changeset
  • Tests (Passing ✅ )
  • Documentation (Updated useEventListener/* 📘 )
  • Backwards compatible ❎ (single optionals into congif (element & options) to previous double optional parameters)

Copy link

changeset-bot bot commented Nov 18, 2024

⚠️ No Changeset found

Latest commit: 5987504

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@JimGitFE JimGitFE changed the title feature: useEventListener Element to Event Map generic override & refactor: multiple overloads to single mapped type feature: useEventListener Element to Event Map generic override + EventTarget & refactor: multiple overloads to single mapped type Nov 20, 2024
@JimGitFE JimGitFE changed the title feature: useEventListener Element to Event Map generic override + EventTarget & refactor: multiple overloads to single mapped type feature: useEventListener Element to Event Map generic override + EventTarget #585 & refactor: multiple overloads to single mapped type Nov 20, 2024
@JimGitFE JimGitFE changed the title feature: useEventListener Element to Event Map generic override + EventTarget #585 & refactor: multiple overloads to single mapped type feature: useEventListener Element to Event Map generic override + EventTarget & refactor: multiple overloads to single mapped type Nov 20, 2024
@JimGitFE JimGitFE changed the title feature: useEventListener Element to Event Map generic override + EventTarget & refactor: multiple overloads to single mapped type feature: useEventListener EventMap generic override + EventTarget & refactor: multiple overloads to single mapped type Nov 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant